#ifndef __DATA_MANAGEMENT_H__
#define __DATA_MANAGEMENT_H__
#include <ros/ros.h>
#include <sensor_msgs/PointCloud2.h>
#include <sensor_msgs/Imu.h>
#include <common/basic_types.h>
#include "common/macro.h"
#include "common/cycarray.h"
#include "pcl_conversions/pcl_conversions.h"

class DataManagement
{
private:
    /* data */
public:
    DataManagement(ros::NodeHandle *nodehandle);
    ~DataManagement();

public:
    void init();
    void start();
    void onIMUDataCallback(const sensor_msgs::Imu::ConstPtr &msg_in);
    void onLidarPointCloudCallback(const sensor_msgs::PointCloud2::ConstPtr &msg_in);

public:
    ros::NodeHandle nh_;
    ros::Subscriber imu_subscriber_;
    ros::Subscriber lidar_raw_point_subscriber_;
    ros::Publisher aft_lidar_point_cloud_publisher_;
    ros::Publisher lidar_objects_publisher_;
    const sensor_msgs::Imu last_imu_data_;
};

class DataProviderRawPointCloud
{
public:
    DataProviderRawPointCloud()
    {
        lspoint_cloud_queue_.Init(1);
    }
    bool Update(const sensor_msgs::PointCloud2::ConstPtr &msg);
    pcl::PointCloud<pcl::PointXYZI> const lspoint_cloud();

    private:
        mutable std::mutex mutex_;
        CycArray<pcl::PointCloud<pcl::PointXYZI>> lspoint_cloud_queue_;
        DECLARE_SINGLETON_WITHOUT_CONSTRUCTOR(DataProviderRawPointCloud);
};

class DataProviderIMUData{
    public:
        DataProviderIMUData(){
            imu_data_queue_.Init(100);
        }

        bool Update(const sensor_msgs::Imu::ConstPtr &msg);
        sensor_msgs::Imu const imu_data();

    private:
        mutable std::mutex mutex_;
        CycArray<sensor_msgs::Imu> imu_data_queue_;
        DECLARE_SINGLETON_WITHOUT_CONSTRUCTOR(DataProviderIMUData);
};

#endif /* __DATA_MANAGEMENT_H__ */